/*
 * vector.h
 *
 *  Created on: Feb 3, 2012
 *      Author: sxzhang
 */

#ifndef VECTOR_H_
#define VECTOR_H_
#define DIMI   			Vector<int>
#define COORDI 			Vector<int>
#define COORDD 			Vector<double>
#define VECTORI 			Vector<int>
#define VECTORD 			Vector<double>
#define ATOMCOORD 		Vector<double>
#define UNITCELLCOORD 	Vector<int>

#define ATOMCOORDLIST  	vector< ATOMCOORD >
#define UNITCELLCOORDLIST	list< UNITCELLCOORD >

#define COORDILIST list< COORDI >
#define COORDDLIST list< COORDD >

#define UNITCELLLIST list < UnitCell >
#define ATOMLIST list< Atom >

#define INLINE inline

template<class T>
struct Vector{
	T x;
	T y;
	T z;

	INLINE Vector<T> operator +(const Vector<T>& v) const;
	INLINE const Vector<T>& operator +=(const Vector<T>& v);

	INLINE Vector<T> operator -(const Vector<T>& v) const;
	INLINE const Vector& operator -=(const Vector<T>& v);

	INLINE Vector<T> operator *(const T& s) const;
	INLINE const Vector<T>& operator *=(const T& s);

	INLINE T abs();
	INLINE bool isZero();
	static INLINE bool isSame(const Vector<T>& v1, const Vector<T>& v2);
	INLINE bool isSameWith(const Vector<T>& v1);

	Vector<T>();
	Vector<T>(T _z, T _y, T _x);
};

template<class T>
INLINE Vector<T> Vector<T>::operator +(const Vector<T>& v) const {
	Vector<T> newV(z + v.z, y + v.y,x + v.x );
	return newV;
}

template<class T>
INLINE const Vector<T>& Vector<T>::operator +=(const Vector<T>& v) {
	x = x + v.x;
	y = y + v.y;
	z = z + v.z;
	return *this;
}

template<class T>
INLINE Vector<T> Vector<T>::operator -(const Vector<T>& c) const {
	Vector<T> newC(z-c.z, y-c.y, x-c.x );
	return newC;
}

template<class T>
INLINE const Vector<T>& Vector<T>::operator -=(const Vector<T>& c){
	x-=c.x;
	y-=c.y;
	z-=c.z;
	return *this;
}

template<class T>
INLINE Vector<T> Vector<T>::operator *(const T& s) const{
	Vector<T> newV(z * s, y * s, x * s);
	return newV;
}

template<class T>
INLINE const Vector<T>& Vector<T>::operator *=(const T& s){
	x *= s;
	y *= s;
	z *= s;
	return *this;
}

template<class T>
INLINE T Vector<T>::abs(){
		return x*x + y*y + z*z;
}

template<class T>
INLINE bool Vector<T>::isZero(){
	return (abs()<0.0001);
}

template<class T>
Vector<T>::Vector(T _z, T _y, T _x){
	x = _x;
	y = _y;
	z = _z;
}

template<class T>
Vector<T>::Vector(){
	x = (T)0;
	y = (T)0;
	z = (T)0;
}

template<class T>
INLINE bool Vector<T>::isSame(const Vector<T>& v1, const Vector<T>& v2){
	return (v1-v2).abs()<0.001;
}

template<class T>
INLINE bool Vector<T>::isSameWith(const Vector<T>& v1){
	return Vector<T>::isSame((*this),v1);
}

#endif /* VECTOR_H_ */
